package com.code.soulspring;

import com.code.soulspring.listener.event.PointEvent;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.io.Resource;

import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Map;

/**
 * 演示spring功能
 *      spring的核心功能是BeanFactory
 *      只不过 applicationContext 组合了 BeanFactory 的功能，并且扩展了很多功能，比如国际化、获取环境变量、获取资源文件，发布事件等
 */
// @SpringBootApplication
public class SoulSpringApplication {

    public static void main(String[] args) throws Exception {
        /**
         * 查看spring上下文对象的具体实现类
         */
        ConfigurableApplicationContext context = SpringApplication.run(SoulSpringApplication.class, args);
        // org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
        System.out.println(context.getClass());

        /**
         * 查看bean工厂对象具体实现类
         */
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // org.springframework.beans.factory.support.DefaultListableBeanFactory
        System.out.println(beanFactory.getClass());

        /**
         * 通过反射拿到spring容器，并遍历查看所有单例bean
         */
        Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        // 设置私有变量可以被访问
        singletonObjects.setAccessible(true);
        Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
        map.entrySet().stream().forEach(System.out::println);

        /**
         * spring国际化功能
         */
        System.out.println(context.getMessage("hi", null, Locale.CHINA));
        System.out.println(context.getMessage("hi", null, Locale.UK));

        /**
         * spring资源文件
         */
        // 如果是类路径下的文件，直接写 classpath 找即可
        Resource resource = context.getResource("classpath:application.properties");
        System.out.println(resource);

        // 如果是在jar包中的文件，写 classpath* 这种通配符方式可以找到
        Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
        for (Resource resource1 : resources) {
            System.out.println(resource1);
        }

        /**
         * 获取环境变量
         */
        System.out.println(context.getEnvironment().getProperty("Path"));
        System.out.println(context.getEnvironment().getProperty("server.port"));

        /**
         * spring发布事件
         */
        context.publishEvent(new PointEvent(context));
    }

}
